package com.lanyun.auth.domain.authUser.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.lanyun.auth.basic.entity.*;
import com.lanyun.auth.basic.po.AuthUserPO;
import com.lanyun.auth.basic.service.*;
import com.lanyun.auth.controller.admin.authUser.vo.AuthUserLoginResponseVO;
import com.lanyun.auth.controller.admin.authUser.vo.AuthUserPageVO;
import com.lanyun.auth.controller.admin.authUser.vo.AuthUserRequestVO;
import com.lanyun.auth.controller.admin.authUser.vo.AuthUserResponseVO;
import com.lanyun.auth.convert.authUser.AuthUserConvert;
import com.lanyun.auth.domain.authUser.AuthUserDomainService;
import com.lanyun.auth.enums.AuthConstant;
import com.lanyun.redis.util.CacheKey;
import com.lanyun.redis.util.RedisUtil;
import com.lanyun.web.bean.PageResult;
import com.lanyun.web.enums.IsDeletedFlagEnum;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

import static com.lanyun.auth.enums.ErrorCodeConstants.*;
import static com.lanyun.exception.util.ServiceExceptionUtil.exception;

/**
 * @Author Jqcc
 * @Version 1.0
 * @Data 2025/3/11
 */
@Service
public class AuthUserDomainServiceImpl implements AuthUserDomainService {

    @Resource
    private AuthUserService authUserService;

    @Resource
    private AuthRoleService authRoleService;

    @Resource
    private AuthUserRoleService authUserRoleService;

    @Resource
    private AuthRolePermissionService authRolePermissionService;

    @Resource
    private AuthPermissionService authPermissionService;

    @Resource
    private RedisUtil redisUtil;


//    @Resource
//    private CacheUtils cacheUtils;

    @Override
    public AuthUserLoginResponseVO doLogin(AuthUserRequestVO authUserRequestVO) {
        AuthUser user = AuthUserConvert.INSTANCE.convert(authUserRequestVO);
        user.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        AuthUser authUser = authUserService.queryByCondition(user);
        if (ObjectUtil.isNull(authUser)) {
            throw exception(AUTH_USER_NOT_EXIST);
        }
        // 缓存用户信息
        String userInfoKey = redisUtil.buildKey(CacheKey.USER_INFO.getCachePrefix(), authUser.getId().toString());
        if (redisUtil.exist(userInfoKey)) {
            redisUtil.del(userInfoKey);
        }
        AuthUserPO authUserPO = AuthUserConvert.INSTANCE.convertToPO(authUser);
        redisUtil.setNx(userInfoKey, JSONUtil.toJsonStr(authUserPO), CacheKey.USER_INFO.getCacheTime(), CacheKey.USER_INFO.getCacheTimeUnit());
        AuthUserLoginResponseVO loginResponseVO = AuthUserConvert.INSTANCE.convert(authUser);
        return loginResponseVO;
    }

    @Override
    public AuthUserResponseVO queryById(Long id) {
        String userInfoKey = redisUtil.buildKey(CacheKey.USER_INFO.getCachePrefix(), id.toString());
        String userInfo = redisUtil.get(userInfoKey);

        if (Strings.isNullOrEmpty(userInfo)) {
            AuthUser authUser = authUserService.queryById(id);
            if (authUser == null) {
                redisUtil.setNx(userInfoKey, "NULL", CacheKey.USER_INFO.getCacheTime(), CacheKey.USER_INFO.getCacheTimeUnit());
                return null;
            }
            AuthUserPO authUserPO = AuthUserConvert.INSTANCE.convertToPO(authUser);
            redisUtil.setNx(userInfoKey, JSONUtil.toJsonStr(authUserPO), CacheKey.USER_INFO.getCacheTime(), CacheKey.USER_INFO.getCacheTimeUnit());
            return convertToResponseVO(authUserPO);
        }

        AuthUserPO authUserPO = JSONUtil.toBean(userInfo, AuthUserPO.class);
        return convertToResponseVO(authUserPO);
    }

    private AuthUserResponseVO convertToResponseVO(AuthUserPO authUserPO) {
        return AuthUserConvert.INSTANCE.convertToResponseVO(authUserPO);
    }


//    public AuthUserResponseVO queryById(Integer id) {
//        String userInfoKey = redisUtil.buildKey(CacheKey.USER_INFO_PREFIX, id.toString());
//        AuthUserPO authUserPO = CacheUtils.getFromCache(userInfoKey, AuthUserPO.class, () -> {
//            AuthUser authUser = authUserService.queryById(id);
//            return authUser != null ? AuthUserConvert.INSTANCE.convertToPO(authUser) : null;
//        }, 1L, TimeUnit.DAYS);
//        return authUserPO != null ? convertToResponseVO(authUserPO) : null;
//    }


    @Override
    public Boolean register(AuthUserRequestVO authUserRequestVO) {
        // 校验用户名是否唯一
        AuthUser user = new AuthUser();
        user.setUsername(authUserRequestVO.getUsername());
        AuthUser res = authUserService.queryByCondition(user);
        if (ObjectUtil.isNotNull(res)) {
            throw exception(AUTH_USER_EXIST);
        }

        AuthUser authUser = AuthUserConvert.INSTANCE.convert(authUserRequestVO);
        AuthUser insertAuthuser = authUserService.insert(authUser);

        // 建立用户角色关联
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAY_USER);
        AuthRole roleResult = authRoleService.queryByCondition(authRole);
        if (ObjectUtil.isNull(roleResult)) {
            throw exception(AUTH_ROLE_NOT_EXIST);
        }
        Long roleId = roleResult.getId();
        Long userId = authUser.getId();

        // 构建用户角色表的实体并插入表中
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(userId);
        authUserRole.setRoleId(roleId);
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        AuthUserRole userRole = authUserRoleService.insert(authUserRole);
        if (ObjectUtils.isEmpty(userRole)) {
            throw exception(AUTH_USER_ROLE_RELEVANCY_FAIL);
        }

        // 把当前用户的角色和权限都刷到redis中
        // 角色相关
        String roleKey = redisUtil.buildKey(CacheKey.AUTH_ROLE.getCachePrefix(), authUser.getUsername());
        List<AuthRole> roleList = new LinkedList<>();
        roleList.add(authRole);
        redisUtil.setNx(roleKey, new Gson().toJson(roleList), CacheKey.AUTH_ROLE.getCacheTime(), CacheKey.AUTH_ROLE.getCacheTimeUnit());

        // 关联角色权限
        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        List<AuthRolePermission> authRolePermissionList = authRolePermissionService
                .queryAllByCondition(authRolePermission);

        List<Long> permissionIdList = authRolePermissionList.stream()
                .map(AuthRolePermission::getPermissionId)
                .collect(Collectors.toList());

        // 根据permissionId查权限
        List<AuthPermission> permissionList = authPermissionService.queryByRoleList(permissionIdList);
        // 将用户权限相关到redis中
        String permissionKey = redisUtil.buildKey(CacheKey.AUTH_PERMISSION.getCachePrefix(), authUser.getUsername());
        redisUtil.setNx(permissionKey, new Gson().toJson(permissionList), CacheKey.AUTH_PERMISSION.getCacheTime(), CacheKey.AUTH_PERMISSION.getCacheTimeUnit());


        return ObjectUtil.isNotNull(insertAuthuser);
    }

    @Override
    public Boolean update(AuthUserRequestVO authUserRequestVO) {
        AuthUser user = new AuthUser();
        user.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        AuthUser authUser = authUserService.queryByCondition(user);
        if (ObjectUtil.isNull(authUser)) {
            throw exception(AUTH_USER_NOT_EXIST);
        }
        AuthUser updateUser = AuthUserConvert.INSTANCE.convert(authUserRequestVO);
        AuthUser updateAuthuser = authUserService.update(updateUser);
        if (ObjectUtil.isNotNull(updateAuthuser)) {
            // 删除缓存
            String userInfoKey = redisUtil.buildKey(CacheKey.USER_INFO.getCachePrefix(), authUser.getId().toString());
            redisUtil.del(userInfoKey);
        }
        return ObjectUtil.isNotNull(updateAuthuser);
    }

    @Override
    public PageResult<AuthUserResponseVO> pageList(AuthUserPageVO authUserPageVO) {
        PageResult<AuthUserResponseVO> pageResult = new PageResult<>();
        Integer start = authUserPageVO.getPage() - 1;
        AuthUser authUser = AuthUserConvert.INSTANCE.convert(authUserPageVO);
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        List<AuthUser> authUserList = authUserService.queryPageByCondition(authUser, start, authUserPageVO.getPageSize());
        if (CollectionUtil.isEmpty(authUserList)) {
            return pageResult;
        }
        List<AuthUserResponseVO> authUserResponseVOList = AuthUserConvert.INSTANCE.convert(authUserList);
        Long count = authUserService.count(authUser);
        pageResult.setPage(authUserPageVO.getPage());
        pageResult.setPageSize(authUserPageVO.getPageSize());
        pageResult.setTotal(count.intValue());
        pageResult.setRecords(authUserResponseVOList);
        return pageResult;
    }

}
